
package org.bridgen.lang.semantics.ast;
import java.util.*;



public class NodeDecl extends Element implements Cloneable {
    public void flushCache() {
        super.flushCache();
        NodeDecl_attrDecls_visited = -1;
        NodeDecl_attrDecls_computed = false;
        NodeDecl_attrDecls_value = null;
    NodeDecl_attrDecls_contributors = new java.util.HashSet();
    }
     @SuppressWarnings({"unchecked", "cast"})  public NodeDecl clone() throws CloneNotSupportedException {
        NodeDecl node = (NodeDecl)super.clone();
        node.in$Circle(false);
        node.is$Final(false);
    return node;
    }
     @SuppressWarnings({"unchecked", "cast"})  public NodeDecl copy() {
      try {
          NodeDecl node = (NodeDecl)clone();
          if(children != null) node.children = (ASTNode[])children.clone();
          return node;
      } catch (CloneNotSupportedException e) {
      }
      System.err.println("Error: Could not clone node of type " + getClass().getName() + "!");
      return null;
    }
     @SuppressWarnings({"unchecked", "cast"})  public NodeDecl fullCopy() {
        NodeDecl res = (NodeDecl)copy();
        for(int i = 0; i < getNumChildNoTransform(); i++) {
          ASTNode node = getChildNoTransform(i);
          if(node != null) node = node.fullCopy();
          res.setChild(node, i);
        }
        return res;
    }
    // Declared in NameAnalysis.jrag at line 32

	
	/**
	 * Checking:
	 * 1) Duplicate declarations of node type within grammar 
	 * TODO Add check of declaration of node type in an other grammar
	 */
	public void nameAnalysis(Collection errorList) {
		NodeDecl decl = lookupNode(getName());
		if (decl != this) { 
			error(errorList, "Duplicate declarations of node type " + getName());
		}
		super.nameAnalysis(errorList);
	}

    // Declared in ParserCodeGen.jrag at line 54

	
	public void generateMethod_match(String indent, StringBuffer buf) {

		if (isAbstract())
			return;

		buf.append(indent + "// " + getName() + "\n");			
		if (hasMultipleStartValues()) {
			buf.append(indent + "for (int i = 0; i < " + getName() + ".START_VALUE.length; i++) {\n");
			buf.append(indent + INDENT + "if (matchForward(content, curPos, " + getName() + ".START_VALUE[i])) {\n");
			buf.append(indent + INDENT + INDENT + "String value = extendMatch(content, curPos, \n");
			buf.append(indent + INDENT + INDENT + indent + getName() + ".START_VALUE[i].length(), " + getName() + ".MATCH_REG_EXP[i]);\n");
			buf.append(indent + INDENT + INDENT + "Interval interval = new Interval(curPos, curPos + value.length() - 1);\n");
			buf.append(indent + INDENT + INDENT + "return new " + getName() + "(previous, interval, value);\n");
			buf.append(indent + INDENT + "}\n");
			buf.append(indent + "}\n\n");
		} else {
			buf.append(indent + "if (matchForward(content, curPos, " + getName() + ".START_VALUE)) {\n");
			buf.append(indent + INDENT + "String value = extendMatch(content, curPos, \n");
			buf.append(indent + INDENT + INDENT + getName() + ".START_VALUE.length(), " + getName() + ".MATCH_REG_EXP);\n");
			buf.append(indent + INDENT + "Interval interval = new Interval(curPos, curPos + value.length() - 1);\n");
			buf.append(indent + INDENT + "return new " + getName() + "(previous, interval, value);\n");
			buf.append(indent + "}\n");
		}
	
	}

    // Declared in ParserCodeGen.jrag at line 169

	
	public void generateSGLRMethod_match(String indent, StringBuffer buf) {
		
		if (isAbstract())
			return;
			
		buf.append(indent + "// " + getName() + "\n");	
		
		buf.append(indent + "for (int i = 0; i < " + getName() + ".TOKEN.length; i++) {\n");
		buf.append(indent + indent + "if (label.equals(" + getName() + ".TOKEN[i]) &&\n");
		buf.append(indent + indent + indent + "  " + "value.matches(" + getName() + ".MATCH_REG_EXP)) {\n");
		buf.append(indent + indent + indent + getName() + " node = new " + getName() + "(previous, interval, value);\n");
		buf.append(indent + indent + indent + "node.setTokenUse(i);\n");
		buf.append(indent + indent + indent + "return node;\n");
		buf.append(indent + indent + "}\n");
		buf.append(indent + "}\n\n");
	}

    // Declared in PreAnalysis.jrag at line 44

	public boolean inBaseLibrary = false;

    // Declared in PreAnalysis.jrag at line 45

	public void setInBaseLibrary(boolean value) {
		inBaseLibrary = value;
	}

    // Declared in TypeAnalysis.jrag at line 21

	
	/**
	 * Checking:
	 * 1) NodeDecl cannot be abstract in source grammar
	 */
	public void typeAnalysis(Collection errorList) {
		if (enclosingGrammar().isFromSource() && isAbstract()) {
			error(errorList, "Abstract node declaration in source grammar");
		}
	}

    // Declared in TypeCodeGen.jrag at line 98

	
	

		
	// Code generation for node declarations
	
	public void generateCode(StringBuffer buf, String packageName) {
		String indent = INDENT;
		
		// Package
		
		if (packageName.trim().length() > 0) {
			buf.append("package " + packageName + ";\n\n");
		}
		
		// Imports
		
		buf.append("import org.briplib.recovery.*;\n");
		buf.append("import org.briplib.recovery.util.*;\n\n"); 
		
		// Class signature
		buf.append("public " + (isAbstract() ? "abstract " : "") + 
			"class " + getName() + " extends " + superClass() + " {\n\n");
		
		// Class attributes
		generateClassAttributes(indent, buf);
		
		// Constructor
		generateConstructor(indent, buf);
		
		// Methods
		generateMethods(indent, buf);
		
		// Attributes
		for (Object obj : attrDecls()) {
			AttrDecl decl = (AttrDecl)obj;
			decl.generateCode(indent, buf);
		}
		
		buf.append("}\n");
	}

    // Declared in TypeCodeGen.jrag at line 136

	
	// Code generation of class attributes
	
	public void generateClassAttributes(String indent, StringBuffer buf) {
		
		//buf.append(indent + "public static final String MATCH_REG_EXP = \"" + regExp() + "\";\n");
	}

    // Declared in TypeCodeGen.jrag at line 379

	
	
	// Code generation of constructors
	
	public void generateConstructor(String indent, StringBuffer buf) {
		// Basic constructor
		buf.append(indent + "public " + getName() + 
			"(LexicalNode previous, Interval interval, String value) {\n");
		buf.append(indent + INDENT + "super(previous, interval, value);\n");
		buf.append(indent + "}\n\n");	
	}

    // Declared in TypeCodeGen.jrag at line 389

	
	// Generate methods
	
	public void generateMethods(String indent, StringBuffer buf) {
		if (!isAbstract()) {
			generateMethod_clone(indent, buf);
		}
	}

    // Declared in TypeCodeGen.jrag at line 701

	
	// Code generation of clone method
	
	public void generateMethod_clone(String indent, StringBuffer buf) {
		// Basic clone method
		buf.append(indent + "public LexicalNode clone(LexicalNode previous) {\n");
		buf.append(indent + INDENT + "return new " + getName() + 
			"(previous, getInterval().clone(), value);\n");
		buf.append(indent + "}\n\n");
	}

    // Declared in bridgit.ast at line 3
    // Declared in bridgit.ast line 20

    public NodeDecl() {
        super();

        setChild(new Opt(), 0);

    }

    // Declared in bridgit.ast at line 11


    // Declared in bridgit.ast line 20
    public NodeDecl(String p0, Opt<NodeUse> p1) {
        setName(p0);
        setChild(p1, 0);
    }

    // Declared in bridgit.ast at line 16


  protected int numChildren() {
    return 1;
  }

    // Declared in bridgit.ast at line 19

  public boolean mayHaveRewrite() { return false; }

    // Declared in bridgit.ast at line 2
    // Declared in bridgit.ast line 20
    protected String tokenString_Name;

    // Declared in bridgit.ast at line 3

    public void setName(String value) {
        tokenString_Name = value;
    }

    // Declared in bridgit.ast at line 6

    public String getName() {
        return tokenString_Name != null ? tokenString_Name : "";
    }

    // Declared in bridgit.ast at line 2
    // Declared in bridgit.ast line 20
    public void setSuperNodeOpt(Opt<NodeUse> opt) {
        setChild(opt, 0);
    }

    // Declared in bridgit.ast at line 6


    public boolean hasSuperNode() {
        return getSuperNodeOpt().getNumChild() != 0;
    }

    // Declared in bridgit.ast at line 10


     @SuppressWarnings({"unchecked", "cast"})  public NodeUse getSuperNode() {
        return (NodeUse)getSuperNodeOpt().getChild(0);
    }

    // Declared in bridgit.ast at line 14


    public void setSuperNode(NodeUse node) {
        getSuperNodeOpt().setChild(node, 0);
    }

    // Declared in bridgit.ast at line 17

     @SuppressWarnings({"unchecked", "cast"})  public Opt<NodeUse> getSuperNodeOpt() {
        return (Opt<NodeUse>)getChild(0);
    }

    // Declared in bridgit.ast at line 21


     @SuppressWarnings({"unchecked", "cast"})  public Opt<NodeUse> getSuperNodeOptNoTransform() {
        return (Opt<NodeUse>)getChildNoTransform(0);
    }

    // Declared in NameAnalysis.jrag at line 111
 @SuppressWarnings({"unchecked", "cast"})     public AttrDecl lookupAttrDecl(String name) {
        AttrDecl lookupAttrDecl_String_value = lookupAttrDecl_compute(name);
        return lookupAttrDecl_String_value;
    }

    private AttrDecl lookupAttrDecl_compute(String name) {
	
		// Attributes in this node
	
		for (Object obj : attrDecls()) {
			AttrDecl attr = (AttrDecl)obj;
			if (attr.getName().equals(name)) {
				return attr;
			}
		}
		
		// Attributes in super node
			
		if (hasSuperNode()) {
			NodeDecl superDecl = getSuperNode().decl();
			if (superDecl != null) {
				return superDecl.lookupAttrDecl(name);
			}
		}
		
		// Predefined attribute values: String value on NodeDecl
		/*
		if (name.equals("value")) {
			return NodeDecl.ATTR_DECL_value;
		}
		*/
		
		return null;
	}

    // Declared in NameAnalysis.jrag at line 273
 @SuppressWarnings({"unchecked", "cast"})     public boolean isNodeDecl() {
        boolean isNodeDecl_value = isNodeDecl_compute();
        return isNodeDecl_value;
    }

    private boolean isNodeDecl_compute() {  return true;  }

    // Declared in NameAnalysis.jrag at line 274
 @SuppressWarnings({"unchecked", "cast"})     public boolean declares(String name) {
        boolean declares_String_value = declares_compute(name);
        return declares_String_value;
    }

    private boolean declares_compute(String name) {  return getName().equals(name);  }

    // Declared in PatternAnalysis.jrag at line 44
 @SuppressWarnings({"unchecked", "cast"})     public boolean hasMultipleStartValues() {
        boolean hasMultipleStartValues_value = hasMultipleStartValues_compute();
        return hasMultipleStartValues_value;
    }

    private boolean hasMultipleStartValues_compute() {  return false;  }

    // Declared in PreAnalysis.jrag at line 43
 @SuppressWarnings({"unchecked", "cast"})     public boolean inBaseLibrary() {
        boolean inBaseLibrary_value = inBaseLibrary_compute();
        return inBaseLibrary_value;
    }

    private boolean inBaseLibrary_compute() {  return inBaseLibrary;  }

    // Declared in TypeAnalysis.jrag at line 80
 @SuppressWarnings({"unchecked", "cast"})     public boolean isIslandDecl() {
        boolean isIslandDecl_value = isIslandDecl_compute();
        return isIslandDecl_value;
    }

    private boolean isIslandDecl_compute() {  return false;  }

    // Declared in TypeAnalysis.jrag at line 85
 @SuppressWarnings({"unchecked", "cast"})     public boolean isAbstract() {
        boolean isAbstract_value = isAbstract_compute();
        return isAbstract_value;
    }

    private boolean isAbstract_compute() {  return false;  }

    // Declared in TypeAnalysis.jrag at line 100
 @SuppressWarnings({"unchecked", "cast"})     public String defaultSuperClass() {
        String defaultSuperClass_value = defaultSuperClass_compute();
        return defaultSuperClass_value;
    }

    private String defaultSuperClass_compute() {  return "LexicalNode";  }

    // Declared in TypeAnalysis.jrag at line 103
 @SuppressWarnings({"unchecked", "cast"})     public String superClass() {
        String superClass_value = superClass_compute();
        return superClass_value;
    }

    private String superClass_compute() {
		if(hasSuperNode()) {
			String name = getSuperNode().decl().getName();
			// Temporary fix: 
			// EndIsland and StartIsland should be added in the base lib grammar
			if (!name.equals("Island")) {
				return name; 
			}
		}
		return defaultSuperClass();
	}

    // Declared in TypeCodeGen.jrag at line 250
 @SuppressWarnings({"unchecked", "cast"})     public boolean forSGLR() {
        boolean forSGLR_value = forSGLR_compute();
        return forSGLR_value;
    }

    private boolean forSGLR_compute() {  return false;  }

    // Declared in TypeCodeGen.jrag at line 254
 @SuppressWarnings({"unchecked", "cast"})     public String value() {
        String value_value = value_compute();
        return value_value;
    }

    private String value_compute() {  return "";  }

    // Declared in TypeCodeGen.jrag at line 301
 @SuppressWarnings({"unchecked", "cast"})     public String regExp() {
        String regExp_value = regExp_compute();
        return regExp_value;
    }

    private String regExp_compute() {  return "";  }

    // Declared in NameAnalysis.jrag at line 228
 @SuppressWarnings({"unchecked", "cast"})     public NodeDecl lookupNode(String name) {
        NodeDecl lookupNode_String_value = getParent().Define_NodeDecl_lookupNode(this, null, name);
        return lookupNode_String_value;
    }

    // Declared in PrettyPrint.jrag at line 19
 @SuppressWarnings({"unchecked", "cast"})     public String indent() {
        String indent_value = getParent().Define_String_indent(this, null);
        return indent_value;
    }

public ASTNode rewriteTo() {
    return super.rewriteTo();
}

    protected int NodeDecl_attrDecls_visited = -1;
    protected boolean NodeDecl_attrDecls_computed = false;
    protected Collection NodeDecl_attrDecls_value;
    // Declared in TypeCodeGen.jrag at line 22
 @SuppressWarnings({"unchecked", "cast"})     public Collection attrDecls() {
        if(NodeDecl_attrDecls_computed)
            return NodeDecl_attrDecls_value;
        if(NodeDecl_attrDecls_visited == boundariesCrossed)
            throw new RuntimeException("Circular definition of attr: attrDecls in class: ");
        NodeDecl_attrDecls_visited = boundariesCrossed;
        int num = boundariesCrossed;
        boolean isFinal = this.is$Final();
        NodeDecl_attrDecls_value = attrDecls_compute();
        if(isFinal && num == boundariesCrossed)
            NodeDecl_attrDecls_computed = true;
        NodeDecl_attrDecls_visited = -1;
        return NodeDecl_attrDecls_value;
    }

    java.util.HashSet NodeDecl_attrDecls_contributors = new java.util.HashSet();
    private Collection attrDecls_compute() {
        ASTNode node = this;
        while(node.getParent() != null && !(node instanceof Program))
            node = node.getParent();
        Program root = (Program)node;
        root.collect_contributors_NodeDecl_attrDecls();
        NodeDecl_attrDecls_value = new ArrayList();
        for(java.util.Iterator iter = NodeDecl_attrDecls_contributors.iterator(); iter.hasNext(); ) {
            ASTNode contributor = (ASTNode)iter.next();
            contributor.contributeTo_NodeDecl_NodeDecl_attrDecls(NodeDecl_attrDecls_value);
        }
        return NodeDecl_attrDecls_value;
    }

    protected void collect_contributors_Grammar_nodeDecls() {
        // Declared in TypeCodeGen.jrag at line 20
        {
            Grammar ref = (Grammar)(enclosingGrammar());
            if(ref != null)
                ref.Grammar_nodeDecls_contributors.add(this);
        }
        super.collect_contributors_Grammar_nodeDecls();
    }
    protected void contributeTo_Grammar_Grammar_nodeDecls(Collection collection) {
        super.contributeTo_Grammar_Grammar_nodeDecls(collection);
        collection.add(this);
    }

}
